package IC.lir;

import java.util.List;

import IC.lir.instructions.ArrayLengthInstruction;
import IC.lir.instructions.BinaryInstruction;
import IC.lir.instructions.BinaryInstructionOp;
import IC.lir.instructions.ConditionalJump;
import IC.lir.instructions.DummyRegister;
import IC.lir.instructions.Instruction;
import IC.lir.instructions.JumpCondition;
import IC.lir.instructions.Label;
import IC.lir.instructions.LabelInstruction;
import IC.lir.instructions.LibraryInstruction;
import IC.lir.instructions.Register;

/**
 * LIR Run Time Checks Class
 */
public class LIRRtc {
	
	private static int RTCCounter = 1;

	public static void AddDivisionByZeroRTC(List<Instruction> iAccumulator,Register r) throws Exception{
		Label str1 = new Label("str1");
		Label RTClb = getUniqeRTCLabel();
		iAccumulator.add(new BinaryInstruction(LIRConstants.IMM_ZERO, r, BinaryInstructionOp.COMPARE));
		iAccumulator.add(new ConditionalJump(RTClb,JumpCondition.FALSE));
		AddPrintNExit(iAccumulator,RTClb,str1);
	}
	
	public static void AddArrayNegativeSizeRTC(List<Instruction> iAccumulator,Register r) throws Exception{
		Label str2 = new Label("str2");
		Label RTClb = getUniqeRTCLabel();
		iAccumulator.add(new BinaryInstruction(LIRConstants.IMM_ZERO, r, BinaryInstructionOp.COMPARE));
		iAccumulator.add(new ConditionalJump(RTClb,JumpCondition.GE));
		AddPrintNExit(iAccumulator,RTClb,str2);
	}
	
	public static void AddArrayIndexOutOfBoundsRTC(List<Instruction> iAccumulator,Register arrReg,Register indexReg) throws Exception{
		Label str3 = new Label("str3");
		Label RTClb =  getUniqeRTCLabel();
		Register len = indexReg.getSuccessor();
		iAccumulator.add(new ArrayLengthInstruction(arrReg,len));
		iAccumulator.add(new BinaryInstruction(indexReg,len, BinaryInstructionOp.COMPARE));
		iAccumulator.add(new ConditionalJump(RTClb,JumpCondition.G));
		AddPrintNExit(iAccumulator,RTClb,str3);
	}
	
	public static void AddNullRTC(List<Instruction> iAccumulator,Register r) throws Exception{
		Label str4 = new Label("str4");
		Label RTClb = getUniqeRTCLabel();
		iAccumulator.add(new BinaryInstruction(LIRConstants.IMM_ZERO, r, BinaryInstructionOp.COMPARE));
		iAccumulator.add(new ConditionalJump(RTClb,JumpCondition.FALSE));
		AddPrintNExit(iAccumulator,RTClb,str4);
	}
	
	private static void AddPrintNExit(List<Instruction> iAccumulator,Label rtc, Label err) throws Exception{
		iAccumulator.add(new LibraryInstruction("println", DummyRegister.Inst(), err));
		iAccumulator.add(new LibraryInstruction("exit", DummyRegister.Inst(), LIRConstants.IMM_ZERO));
		iAccumulator.add(new LabelInstruction(rtc));
	}
	
	private static Label getUniqeRTCLabel() {
		return new Label("_RTClb"+ RTCCounter++);
	}
	
}
